package com.sys.plat.ExtDirect;

import com.softwarementors.extjs.djn.StringUtils;
import com.softwarementors.extjs.djn.config.ApiConfiguration;
import com.softwarementors.extjs.djn.servlet.DirectJNgineServlet;
import com.softwarementors.extjs.djn.servlet.ServletConfigurationException;
import com.softwarementors.extjs.djn.servlet.ServletUtils;
import com.sys.plat.web.core.ActionContext;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;

/**
 * Created by IntelliJ IDEA.
 * User: mabo
 * Date: 2010-3-15
 * Time: 14:12:08
 * To change this template use File | Settings | File Templates.
 */
public class MyDirectJNgineServlet extends DirectJNgineServlet {
    private static final Logger logger = Logger.getLogger(DirectJNgineServlet.class);

    private static final String APIS_PARAMETER = "apis";
    private static final String VALUES_SEPARATOR = ",";


    public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ActionContext.requestLocal.set(request);
		ActionContext.responseLocal.set(response);
        super.doPost(request,response);
    }

    protected List<ApiConfiguration> createApiConfigurationsFromServletConfigurationApi(ServletConfig configuration) {
        assert configuration != null;

        List<ApiConfiguration> result = new ArrayList<ApiConfiguration>();
        String configFile = ServletUtils.getRequiredParameter(configuration, "configFile");

        for (String config : configFile.split(",")) {

            String cf = getServletContext().getRealPath(config);
            File f = new File(cf);
            SAXReader reader = new SAXReader();
            Document doc = null;
            try {
                doc = reader.read(f);
            } catch (DocumentException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }
            Element root = doc.getRootElement();
            Iterator i = root.elementIterator("Api");
            while (i.hasNext()) {
                Element e = (Element) i.next();
                ApiConfiguration apiConfiguration = createApiConfigurationFromServletConfigurationApi(e);
                result.add(apiConfiguration);
            }
        }
        if (result.isEmpty()) {
            logger.warn("No apis specified");
        }

        return result;
    }


    protected ApiConfiguration createApiConfigurationFromServletConfigurationApi(Element e) {

        String api = e.attributeValue("name");
        String apiFile = e.elementText("File");
        String fullGeneratedApiFile = getServletContext().getRealPath(apiFile);
        String apiNamespace = e.elementText("apiNamespace");
        String actionsNamespace = e.elementText("actionsNamespace");

        if (apiNamespace.equals("")) {
            if (actionsNamespace.equals("")) {
                apiNamespace = ApiConfiguration.DEFAULT_NAMESPACE_PREFIX + api;
                if (logger.isDebugEnabled()) {
                    logger.debug("Using the api name, prefixed with '" + ApiConfiguration.DEFAULT_NAMESPACE_PREFIX + "' as the value for " + ApiParameters.API_NAMESPACE);
                }
            } else {
                apiNamespace = actionsNamespace;
                logger.debug("Using " + ApiParameters.ACTIONS_NAMESPACE + " as the value for " + ApiParameters.API_NAMESPACE);
            }
        }

        StringBuffer cnb = new StringBuffer();
        Iterator c = e.element("classes").elementIterator("param");
        while (c.hasNext()) {
            Element ec = (Element) c.next();
            cnb.append(ec.getText()).append(",");
        }

        String classNames = cnb.toString().substring(0, cnb.length() - 1);

        List<Class<?>> classes = getClasses(classNames);

        if (logger.isInfoEnabled()) {
            logger.info("Servlet '" + api + "' Api configuration: " +
                    ApiParameters.API_NAMESPACE + "=" + apiNamespace + ", " +
                    ApiParameters.ACTIONS_NAMESPACE + "=" + actionsNamespace + ", " +
                    ApiParameters.API_FILE + "=" + apiFile + " => Api file: " + fullGeneratedApiFile + ", " +
                    ApiParameters.CLASSES + "=" + classNames);
        }

        if (classes.isEmpty()) {
            logger.warn("There are no action classes to register for api '" + api + "'");
        }
        ApiConfiguration apiConfiguration = new ApiConfiguration(api, fullGeneratedApiFile, apiNamespace, actionsNamespace, classes);
        return apiConfiguration;
    }


    private static List<Class<?>> getClasses(String classes) {
        assert classes != null;

        List<Class<?>> result = new ArrayList<Class<?>>();
        if (StringUtils.isEmpty(classes)) {
            return result;
        }
        List<String> classNames = StringUtils.getNonBlankValues(classes, VALUES_SEPARATOR);

        for (String className : classNames) {
            try {
                Class<?> cls = Class.forName(className);
                result.add(cls);
            }
            catch (ClassNotFoundException ex) {
                logger.fatal(ex.getMessage(), ex);
                ServletConfigurationException e = ServletConfigurationException.forClassNotFound(className, ex);
                throw e;
            }
        }

        return result;
    }
}
